package data

import (
	"context"
	"fmt"
	"github.com/go-kratos/kratos/v2/log"
	"github.com/go-redis/redis/v8"
	"github.com/google/wire"
	"gorm.io/gorm"
	"stwin.net/zoro/zdata"
)

// 此文件无需做任何改动

// data providers. *Data, biz.Repo, error
var ProviderSet = wire.NewSet(zdata.NewMDB, zdata.NewRDB, zdata.NewZDataModel, NewDataRepo)

type Repo struct {
	*zdata.ZDataModel
	log *log.Helper
}

func (r *Repo) InTx(ctx context.Context, fn func(ctx context.Context) error) error {
	return r.ZDataModel.MDB.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
		ctx = context.WithValue(ctx, contextTxKey{}, tx)
		return fn(ctx)
	})
}

type contextTxKey struct{}

// 对外再暴露一个 获取 方法
func (r *Repo) MDB(ctx context.Context) *gorm.DB {
	tx, ok := ctx.Value(contextTxKey{}).(*gorm.DB)
	if ok {
		return tx
	}
	return r.ZDataModel.MDB
}

func (r *Repo) RDB(ctx context.Context) *redis.Client {
	return r.ZDataModel.RDB.WithContext(ctx)
}

func NewDataRepo(zDataModel *zdata.ZDataModel, logger log.Logger) (*Repo, func()) {
	l := log.NewHelper(logger)
	r := &Repo{
		ZDataModel: zDataModel,
		log:        l,
	}

	return r, func() {
		fmt.Println("正在关闭 data 数据 ...")
		// 最终需要关闭的连接
		if zDataModel != nil && zDataModel.RDB != nil {
			err := r.ZDataModel.RDB.Close()
			if err != nil {
				l.Errorf("关闭 redis 失败... err = %v", err)
			}
		}
	}
}
